﻿using System.Collections.Generic;
using System.ServiceProcess;
using CID.Domain.Development;
using CID.Execution.Controller.Service.Configuration;
using CID.Execution.Support.Contracts;
using CID.Execution.Support.DeploymentInitiation;
using CID.Execution.Support.DeploymentInitiation.Configuration;
using CID.Execution.Support.PackageRegistration;
using CID.Execution.Support.PackageRegistration.Configuration;
using NailsFramework;

namespace CID.Execution.Controller.Service
{
    static class Program
    {
        private static List<IPackageRegistrationServiceConfigurator> packageRegistrationServiceConfigurators = new List<IPackageRegistrationServiceConfigurator>();
        private static List<IDeploymentInitiationServiceConfigurator> deploymentInitiationServiceConfigurators = new List<IDeploymentInitiationServiceConfigurator>();

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            ConfigureNails();
            ConfigureAdditionalServices();

            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
			{ 
				new ControllerWindowsService() 
			};

            SetUpAdditionalServices();
            ServiceBase.Run(ServicesToRun);
            TearDownAdditionalServices();
        }

        private static void ConfigureNails()
        {
            Nails.Configure()
                .IoC.Container<NailsFramework.IoC.Unity>()
                .UnitOfWork.ConnectionBoundUnitOfWork(true) 
                .Persistence.DataMapper<NailsFramework.Persistence.NHibernate>(CID.Domain.Persistence.Configuration.Configure)
                .UserInterface.Platform<NailsFramework.UserInterface.NullUIPlatform>()
                .Logging.Logger<NailsFramework.Logging.Log4net>()
                .InspectAssemblyOf<IComponent>()
                .InspectAssemblyOf<Controller>()
                .InspectAssemblyOf<IPackageRegistrator>()
                .Aspects.ApplyBehavior<NailsFramework.UnitOfWork.UnitOfWorkBehavior>().ToInheritorsOf<IControllerService>()
                .Aspects.ApplyBehavior<NailsFramework.UnitOfWork.UnitOfWorkBehavior>().ToInheritorsOf<IDeploymentInitiator>()
                .Aspects.ApplyBehavior<NailsFramework.UnitOfWork.UnitOfWorkBehavior>().ToInheritorsOf<IPackageRegistrator>()
                .Initialize();
        }

        private static void ConfigureAdditionalServices()
        {
            foreach (PackageRegistrationServiceConfiguratorElement serviceConfigurator in ApplicationConfiguration.PackageRegistrationConfiguration.ServiceConfigurators)
                packageRegistrationServiceConfigurators.Add(serviceConfigurator.GetConfigurator());

            foreach (DeploymentInitiationServiceConfiguratorElement serviceConfigurator in ApplicationConfiguration.DeploymentInitiationConfiguration.ServiceConfigurators)
                deploymentInitiationServiceConfigurators.Add(serviceConfigurator.GetConfigurator());
        }

        private static void SetUpAdditionalServices()
        {
            foreach (var serviceConfigurator in packageRegistrationServiceConfigurators)
                serviceConfigurator.SetUp();

            foreach (var serviceConfigurator in deploymentInitiationServiceConfigurators)
                serviceConfigurator.SetUp();
        }

        private static void TearDownAdditionalServices()
        {
            foreach (var serviceConfigurator in packageRegistrationServiceConfigurators)
                serviceConfigurator.TearDown();

            foreach (var serviceConfigurator in deploymentInitiationServiceConfigurators)
                serviceConfigurator.TearDown();
        }
    }
}
